#include "TcpConnection.hpp"
#include "InetAddress.hpp"
#include "EventLoop.hpp"


#include <sstream>

using std::ostringstream;

namespace wd
{
TcpConnection::TcpConnection(int fd)
    :_socket(fd)
     ,_socketIO(fd)
     ,_clientAddr(getClientName())
     ,_peerAddr(getPeerName())
    {}

void TcpConnection::send(const string &str){
    if(str.size()){
        _socketIO.sendn(str.c_str(),str.size());
    }
}

string TcpConnection::receive(){
    char buf[65535] ={0};
    int ret=_socketIO.getline(buf,sizeof(buf));
    return string(buf,ret);
}

bool TcpConnection::isClosed()const{
    char buf[20] ={0};
    return _socketIO.recvPeek(buf,sizeof(buf)) ==0;
}

InetAddress TcpConnection::getClientName(){
    struct sockaddr_in addr;
    socklen_t len = sizeof(addr);
    
    int ret = getsockname(_socket.getFd(),(struct sockaddr*)&addr,&len);
    if(ret <0){
        perror("getsockname");
    }
    return InetAddress(addr);
}

InetAddress TcpConnection::getPeerName(){
    struct sockaddr_in addr;
    socklen_t len = sizeof(addr);

    int ret = getpeername(_socket.getFd(),(struct sockaddr*)&addr,&len);
    if(ret <0){
        perror("getpeername");
    }
    return InetAddress(addr);
}

string TcpConnection::connectionInfo(){
    ostringstream oss;
    oss<<"tcp "<<_clientAddr.ip()<<" "<<_clientAddr.port()
        <<"--->"<<_peerAddr.ip()<<" "<<_peerAddr.port();
    return oss.str();
}

string TcpConnection::clientInfo(){
    ostringstream oss;
    oss<<"tcp "<<_clientAddr.ip()<<" "<<_clientAddr.port();
    return oss.str();
}

string TcpConnection::peerInfo(){
    ostringstream oss;
    oss<<"tcp "<<_peerAddr.ip()<<" "<<_peerAddr.port();
    return oss.str();
}

void TcpConnection::shotdown(){
    _socket.shotdownWrite();
}

void TcpConnection::setCallBack(const CallBack &cb1,
                                const CallBack &cb2,
                                const CallBack &cb3)
{
    _onConnection = cb1;
    _onMessage = cb2;
    _onClosed = cb3;
}

void TcpConnection::handleNewConnectionCallBack(){
    if(_onConnection){
        _onConnection(shared_from_this());
    }
}

void TcpConnection::handleMessageCallBack(){
    if(_onMessage){
        _onMessage(shared_from_this());
    }
}

void TcpConnection::handleOnClosedCallBack(){
    if(_onClosed){
        _onClosed(shared_from_this());
    }
}

void TcpConnection::sendToLoop(const string &msg){
    if(_loop){
        _loop->functorToLoop(std::bind(&TcpConnection::send,this,msg));
    } 
}

}//end of namespace
